home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mm / mm-0.90 / more.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-18  |  5.4 KB  |  265 lines

  1. /*
  2.  * Copyright (c) 1986, 1990 by The Trustees of Columbia University in
  3.  * the City of New York.  Permission is granted to any individual or
  4.  * institution to use, copy, or redistribute this software so long as it
  5.  * is not sold for profit, provided this copyright notice is retained.
  6.  */
  7.  
  8. #ifndef lint
  9. static char *rcsid = "$Header: /f/src2/encore.bin/cucca/mm/tarring-it-up/RCS/more.c,v 2.1 90/10/04 18:25:06 melissa Exp $";
  10. #endif
  11.  
  12. /* 
  13.  * more.c - routines for displaying messages (the 'type' command, etc),
  14.  * by piping them through "more" if appropriate
  15.  *
  16.  */
  17.  
  18. #include "mm.h"
  19. #include "parse.h"
  20.  
  21. char *malloc ();
  22. FILE *mm_popen ();
  23.  
  24. #define H_END    0
  25. #define H_SKIP    1
  26. #define H_OK    2
  27.  
  28. /*
  29.  * bad_header - succeeds if header should be skipped according to
  30.  * how user has specified only-type-headers and dont-type-headers.
  31.  */
  32.  
  33. int
  34. bad_header (line, only, dont)
  35. char *line;
  36. char **only;
  37. char **dont;
  38. {
  39.     char *p;
  40.  
  41.     if (only != (char **) NULL) {
  42.     while (p = *only++)
  43.         if (hdrcmp (p, line))
  44.         return false;
  45.     return true;
  46.     }
  47.     if (dont != (char **) NULL) {
  48.     while (p = *dont++)
  49.         if (hdrcmp (p, line))
  50.         return true;
  51.     }
  52.     return false;
  53. }
  54.  
  55. /*
  56.  * span - find the length of the leading substring of s1 containing
  57.  * only those characters from set s2
  58.  */
  59.  
  60. int
  61. span (s1, s2)
  62. char *s1, *s2;
  63. {
  64.     char c;
  65.     char *p;
  66.     int n = 0;
  67.  
  68.     while (c = *s1++) {
  69.     p = s2;
  70.     while (*p && c != *p)
  71.         p++;
  72.     if (*p == 0)
  73.         break;
  74.     n++;
  75.     }
  76.     return n;
  77. }
  78.  
  79. int
  80. logical_lines (s, max)
  81. char *s;
  82. int max;
  83. {
  84.     int n, pos;
  85.  
  86.     for (n = 0, pos = 0; *s; s++)    /* count newlines, long lines */
  87.     if (*s == '\n' || ++pos > cmcsb._cmcmx) {
  88.         n++, pos = 0;
  89.         if (n == max) return n;    /* stop if no point in continuing */
  90.     }
  91.     if (pos) n++;            /* count partial last line */
  92.     return n;
  93. }
  94.  
  95. char *
  96. fmt_message (m, only, dont)
  97. message *m;
  98. char **only, **dont;
  99. {
  100.     char *buf, *cur;
  101.     char *p = m->text;
  102.     int left = m->size;
  103.     int context = H_OK;
  104.     int linelength;
  105.     char c;
  106.  
  107.     buf = malloc (m->size + 4);
  108.     if (buf == NULL) {
  109.     fprintf (stderr, "fmt_message: out of memory\n");
  110.     return(NULL);
  111.     }
  112.  
  113.     cur = buf;
  114.     while (left > 0 && context != H_END) {
  115.     if (*p == '\n' || *p == '\0')
  116.         context = H_END;
  117.     else
  118.         context = (bad_header (p, only, dont) ? H_SKIP : H_OK);
  119.     linelength = skipheader (p) - p;
  120.     switch (context) {
  121.       case H_OK:            /* normal header */
  122.         strncpy (cur, p, linelength);
  123.         cur += linelength;
  124.         /* fall through */
  125.       case H_SKIP:            /* header user doesn't want */
  126.         p += linelength;
  127.         left -= linelength;
  128.         break;
  129.       case H_END:            /* end of headers or error */
  130.         break;
  131.     }
  132.     }
  133.  
  134.     /* copy out the rest of the message */
  135.     while (left > 0 && (c = *p++)) {
  136.     *cur++ = c;
  137.     --left;
  138.     }
  139.  
  140.     if (cur > buf && (cur[-1] != '\n'))
  141.     *cur++ = '\n';            /* drop in terminating newline */
  142.  
  143.     *cur = 0;                /* null-terminate the message */
  144.  
  145.     if (left != 0)
  146.     fprintf (stderr, "fmt_message: expected %d chars, had %d left over\n",
  147.          m->size, left);
  148.     return buf;
  149. }
  150.  
  151. display_message (out, m, maybeclear, only, dont)
  152. FILE *out;
  153. message *m;
  154. int maybeclear;
  155. char **only, **dont;
  156. {
  157.     char *msg;
  158.     FILE *fp;
  159.     FILE *more_pipe_open();
  160.     extern int use_crt_filter_always;
  161.     int c;
  162.     msg = fmt_message (m, only, dont);
  163.     if (msg == NULL) return 0;
  164.     
  165.     if (maybeclear && clear_screen && (out == stdout))
  166.     blank ();
  167.  
  168.     if (use_crt_filter_always ||
  169.     (logical_lines (msg, cmcsb._cmrmx) +1 >= cmcsb._cmrmx)) {
  170.     fp = more_pipe_open(out);
  171.     }
  172.     else
  173.     fp = out;            /* not long, just write it */
  174.  
  175.     c = (int) (m - cf->msgs);
  176.     fprintf (fp, " Message %d (%d chars)\n", c, m->size);
  177. #ifdef sun_stdio_bug
  178.     fwrite (msg, sizeof(char), strlen(msg), fp);
  179. #else
  180.     fputs (msg, fp);
  181. #endif /* sun_stdio_bug */
  182.     free (msg);
  183.     if (fp == out) {             /* not a pipe */
  184.     fflush (fp);
  185.     return(false);
  186.     }
  187.     more_pipe_close(fp);        /* really a pipe */
  188.     return(true);
  189. }
  190.  
  191.  
  192. /* for more_pipe_open and _close */
  193. static signalhandler (*old_sigpipe)();
  194. static int pipe_broke;
  195. static signalhandler (*sigint)(), (*sigtstp)(), (*sigquit)();
  196.  
  197. signalhandler
  198. on_sigpipe ()
  199. {
  200.     pipe_broke = 1;
  201.     signal (SIGPIPE, on_sigpipe);
  202. }
  203.  
  204. /*
  205.  * more_pipe_open:
  206.  * try to open the pipe to more our message, return either the pipe FILE *
  207.  * or the FILE * we were given
  208.  */
  209. FILE *
  210. more_pipe_open (out)
  211. FILE *out;
  212. {
  213.     FILE *fp;
  214.     int n;
  215.  
  216.     if ((out == stdout) &&
  217.     (isatty (fileno (out))) &&
  218.     (cmcsb._cmrmx > 0) &&
  219.     (crt_filter[0] != 0)) {
  220.     fflush (stdout);
  221.     fflush (stderr);
  222.     cmtend ();            /* shut off ccmd's control of tty */
  223.     if (fp = mm_popen (crt_filter, "w")) {
  224.         pipe_broke = 0;
  225.         old_sigpipe = signal (SIGPIPE, on_sigpipe);
  226.         fflush (stdout);
  227.         fflush (stderr);
  228. #ifdef SIGTSTP
  229.         sigtstp = signal (SIGTSTP, SIG_DFL), 
  230. #endif
  231.         sigint = signal (SIGINT, SIG_IGN),
  232.         sigquit = signal (SIGQUIT, SIG_IGN);
  233.         return (fp);
  234.     }
  235.     else {
  236.         cmtset ();
  237.         cmcsb._cmwrp = autowrap_column; /* gets reset */
  238.         return (out);        /* can't open pipe, send to stdout */
  239.     }
  240.     }
  241.     return(out);            /* use what they gave us */
  242. }
  243.  
  244. /*
  245.  * more_pipe_close:
  246.  * clean up and close this pipe
  247.  */
  248. more_pipe_close(fp)
  249. FILE *fp;
  250. {
  251.     signal (SIGPIPE, SIG_IGN);
  252.     mm_pclose (fp);
  253.     signal (SIGPIPE, old_sigpipe);
  254.     signal (SIGINT, sigint),
  255.     signal (SIGQUIT, sigquit);
  256. #ifdef SIGTSTP
  257.     signal (SIGTSTP, sigtstp);
  258. #endif
  259.     fflush(stdout);
  260.     cmtset ();                /* setup tty for ccmd again */
  261.     cmcsb._cmwrp = autowrap_column;    /* gets reset */
  262.     return;
  263. }
  264.     
  265.